using System;
using System.Collections.Generic;
using System.Text;

namespace Xfinity.Engine
{
    /// <summary>
    /// Event arguments for when information is updated.
    /// </summary>
    public class InformationUpdatedEventArgs:EventArgs
    {
        public InformationUpdatedEventArgs(object source)
        {
            this.source = source;
        }
        private object source;

        /// <summary>
        /// The source of the change.
        /// </summary>
        public object Source
        {
            get { return source; }
        }

    }
    /// <summary>
    /// A piece of information.
    /// </summary>
    public class Information:MarshalByRefObject
    {
        /// <summary>
        /// Constructs a new piece of information.
        /// </summary>
        /// <param name="data">The initial data.</param>
        /// <param name="source">The initial source of the data.</param>
        public Information(object data, object source)
        {
            this.data.Push(data);
            this.source.Push(source);
        }
        private object tag = new object();

        /// <summary>
        /// Misc. data.
        /// </summary>
        public object Tag
        {
            get { return tag; }
            set { tag = value; }
        }
        /// <summary>
        /// Called when the blackboard is updated.
        /// </summary>
        public event EventHandler<InformationUpdatedEventArgs> InformationUpdated = delegate{ };
        private Stack<object> source = new Stack<object>();

        /// <summary>
        /// The source of the information.
        /// </summary>
        public object Source
        {
            get { return source.Peek(); }
        }
        /// <summary>
        /// Returns the source history.
        /// </summary>
        public Stack<object> SourceHistory
        {
            get { return source; }
        }

        /// <summary>
        /// Update the data.
        /// </summary>
        /// <param name="data">The new data.</param>
        /// <param name="source">The source of the information.</param>
        public void UpdateData(object data, object source)
        {
            this.data.Push(data);
            this.source.Push(source);

            EventHandler<InformationUpdatedEventArgs> temp = InformationUpdated;
            if (temp != null)
            {
                temp(this, new InformationUpdatedEventArgs(source));
            }
        }

        private Stack<object> data =new Stack<object>();
        /// <summary>
        /// The main data.
        /// </summary>
        public object Data
        {
            get { return data.Peek(); }
        }
        /// <summary>
        /// Returns the data history.
        /// </summary>
        public Stack<object> DataHistory
        {
            get { return data; }
        }

    }

    /// <summary>
    /// A collection of information.
    /// </summary>
    public class BlackboardDiagram:MarshalByRefObject
    {
        private Dictionary<string, Information> information;

        /// <summary>
        /// Gets all the knowledge on the blackboard.
        /// </summary>
        public Dictionary<string, Information> AvailableInformation
        {
            get { return information; }
        }
        /// <summary>
        /// Constructs a new blackboard.
        /// </summary>
        public BlackboardDiagram()
        {
            information = new Dictionary<string, Information>();
        }
        public List<object> FindCommonInformation()
        {
            throw new NotImplementedException();
            List<object> info = new List<object>();

            foreach (KeyValuePair<string,Information> o in information)
            {
                foreach (KeyValuePair<string, Information> check in information)
                {
                    if (object.ReferenceEquals(check.Value, o.Value))
                    {
                        continue;
                    }
                    object current = check.Value.DataHistory.Pop();

                    foreach (object history in check.Value.DataHistory)
                    {
                        if (true)
                        {
                            
                        }
                    }
                    check.Value.DataHistory.Push(current);
                }
            }
            return info;
        }
        /// <summary>
        /// Constructs a new blackboard.
        /// </summary>
        /// <param name="information">An existing collection of information.</param>
        public BlackboardDiagram(IDictionary<string,Information> information)
        {
            this.information = new Dictionary<string, Information>(information);
        }
        /// <summary>
        /// Constructs a new blackboard.
        /// </summary>
        /// <param name="information">An existing collection of information.</param>
        public BlackboardDiagram(IEnumerable<KeyValuePair<string,Information>> information)
        {
            this.information = new Dictionary<string, Information>();
            foreach (KeyValuePair<string,Information> pair in information)
            {
                this.information.Add(pair.Key, pair.Value);
            }
        }
    }
}
